package cn.tonyandmoney.baidu.asr.adapter

import android.text.TextUtils
import cn.tonyandmoney.baidu.asr.controller.ErrorTranslation
import cn.tonyandmoney.baidu.asr.entity.NluResult
import cn.tonyandmoney.baidu.asr.recognizer.IRecogListener
import cn.tonyandmoney.baidu.asr.recognizer.RecogResult
import com.baidu.speech.aidl.EventListener
import com.baidu.speech.asr.SpeechConstant
import org.jetbrains.anko.AnkoLogger
import org.jetbrains.anko.error
import org.json.JSONException
import org.json.JSONObject

/**
 * Created by niantuo on 2018/2/8.
 * 识别适配器
 */
open class RecogEventAdapter(private val callback: IRecogListener)
    : EventListener.Stub(), AnkoLogger {

    override fun onEvent(name: String, params: String, data: ByteArray?, offset: Int, length: Int) {
        if (name == SpeechConstant.CALLBACK_EVENT_ASR_LOADED) {
            callback.onOfflineLoaded()
        } else if (name == SpeechConstant.CALLBACK_EVENT_ASR_UNLOADED) {
            callback.onOfflineUnLoaded()
        } else if (name == SpeechConstant.CALLBACK_EVENT_ASR_READY) {
            // 引擎准备就绪，可以开始说话
            callback.onAsrReady()
        } else if (name == SpeechConstant.CALLBACK_EVENT_ASR_BEGIN) {
            // 检测到用户的已经开始说话
            callback.onAsrBegin()
        } else if (name == SpeechConstant.CALLBACK_EVENT_ASR_END) {
            // 检测到用户的已经停止说话
            callback.onAsrEnd()
        } else if (name == SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL) {  // 临时识别结果, 长语音模式需要从此消息中取出结果
            val recogResult = RecogResult.parseJson(params)
            var nluResult = NluResult()
            if (!TextUtils.isEmpty(recogResult.results_nlu)) {
                nluResult = NluResult.fromJson(recogResult.results_nlu)
            }
            val results = recogResult.resultsRecognition
            if (recogResult.isFinalResult) {
                callback.onAsrFinalResult(results, recogResult, nluResult)
            } else if (recogResult.isPartialResult) {
                callback.onAsrPartialResult(results, recogResult, nluResult)
            }
        } else if (name == SpeechConstant.CALLBACK_EVENT_ASR_FINISH) {
            // 识别结束， 最终识别结果或可能的错误
            val recogResult = RecogResult.parseJson(params)
            if (recogResult.hasError()) {
                val errorCode = recogResult.error
                val subErrorCode = recogResult.subError
                callback.onAsrFinishError(errorCode, subErrorCode, ErrorTranslation.recogError(errorCode), recogResult.desc, recogResult)
            } else {
                callback.onAsrFinish(recogResult)
            }
        } else if (name == SpeechConstant.CALLBACK_EVENT_ASR_LONG_SPEECH) { //长语音
            callback.onAsrLongFinish()// 长语音
        } else if (name == SpeechConstant.CALLBACK_EVENT_ASR_EXIT) {
            callback.onAsrExit()
        } else if (name == SpeechConstant.CALLBACK_EVENT_ASR_VOLUME) {
            val (volumePercent, volume) = parseVolumeJson(params)
            callback.onAsrVolume(volumePercent, volume)
        } else if (name == SpeechConstant.CALLBACK_EVENT_ASR_AUDIO) {
            if (data?.size ?: 0 != length) {
                error("internal error: asr.audio callback data length is not equal to length param")
            } else {
                callback.onAsrAudio(data, offset, length)
            }
        }
    }

    private fun parseVolumeJson(jsonStr: String): Volume {
        val vol = Volume()
        vol.original = jsonStr
        try {
            val json = JSONObject(jsonStr)
            vol.volumePercent = json.getInt("volume-percent")
            vol.volume = json.getInt("volume")
        } catch (e: JSONException) {
            e.printStackTrace()
        }

        return vol
    }

    private data class Volume(var volumePercent: Int = -1,
                              var volume: Int = -1,
                              var original: String? = null)

}